#!/usr/bin/env ruby

# Copyright 2024 Henrique Paone
#
# This file is part of Kitty-Visual.
#
# Kitty-Visual is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
# 
# Kitty-Visual is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along with
# Kitty-Visual. If not, see <https://www.gnu.org/licenses/>.

require 'pty'
require 'tempfile'
require 'fileutils'
require 'io/console'
require 'msgpack/rpc'
require 'msgpack/rpc/transport/unix'

require_relative 'lib/nvim.rb'
require_relative 'lib/screen.rb'

include Tui
include Kitty 

CTRL_V = "\u0016"
Backspace = "\u007f"
Visual_modes = ['v', 'V', CTRL_V]

def isvisual?(mode)
  Visual_modes.include? mode
end

def clean_scrollback(scrollback)
  scrollback.map do |line| 
    line.gsub(/(#{ Ansi_regex })|(#{ Kitty_builtin_regex })/, '')
  end
end

# Get scrollback
scrollback = ARGF.read
scrollback = scrollback.split "\n"
  
# Kitty pipes the scrollback, so we need to reopen STDIN to read input
STDIN.reopen '/dev/stdout'
data = get_kitty_data
scrolled = data[:scrolled]
lines = data[:lines]
cols = data[:cols]
cline = data[:cline]
ccol = data[:ccol]

nvim = Nvim.new
screen = Screen.new(
  nvim.get_bg_color('Visual'), nvim.get_bg_color('Search'),
  lines, cols, scrolled, cline, ccol, scrollback
)

nvim.scrollback = clean_scrollback(screen.contents_wrapped)
nvim.cursor(screen.cursor)

trap("WINCH") do
  height, width = IO.console.winsize
  screen.resized = true
  screen.height = height
  screen.width = width
  nvim.scrollback = clean_scrollback(screen.contents_wrapped)
  nvim.cursor(screen.cursor)
  screen.update
end

old_mode = 'n'
cmdtype = ''

# Main event loop
loop do
  key = parse_escaped(get_escaped)
  next if key.nil?
  exit if key == '<Esc>'
  nvim.input key
  state = nvim.get_mode
  next if state['blocking']
  _, l, c, _ = nvim.getpos('.')
  # Command mode
  if state['mode'] == 'c'
    cmdline = nvim.getcmdline
    if old_mode != 'c' # First time entering
      old_mode = 'c'
      screen.move_cursor lines, 1
      cmdtype = nvim.getcmdtype
      print cmdtype
    end
    screen.move_cursor lines, 2
    screen.clear_current_line
    print "#{ cmdline }"
    screen.move_cursor lines, nvim.getcmdpos + 1
   next
  elsif old_mode == 'c'
    old_mode = state['mode']
    if ['/', '?'].include?(cmdtype)
      pattern = nvim.getreg('/') 
      screen.match(nvim.getreg('/'), nvim.scrollback)
    end
  # Visual mode
  elsif isvisual? state['mode']
    old_mode = state ['mode'] unless isvisual? old_mode
    screen.selection = nvim.get_selection
  elsif isvisual? old_mode
    screen.selection = []
    old_mode = state['mode']
  end
  screen.cursor = l, c
  screen.update 
end
